//! 字符串类型(文)的完整实现
//!
//! 设计原则：
//! - 支持Unicode字符处理
//! - 提供丰富的字符串操作方法
//! - 支持正则表达式和模式匹配
//! - 智能处理编码和格式转换

/// 字符串工具类，提供静态方法
pub struct StringUtils;

impl StringUtils {
    /// 检查字符串是否为空或仅包含空白字符
    pub fn is_blank(s: &str) -> bool {
        s.trim().is_empty()
    }

    /// 检查字符串是否只包含空白字符
    pub fn is_whitespace(s: &str) -> bool {
        s.chars().all(|ch| ch.is_whitespace())
    }

    /// 检查字符串是否只包含数字
    pub fn is_numeric(s: &str) -> bool {
        !s.is_empty() && s.chars().all(|ch| ch.is_numeric())
    }

    /// 检查字符串是否只包含字母
    pub fn is_alphabetic(s: &str) -> bool {
        !s.is_empty() && s.chars().all(|ch| ch.is_alphabetic())
    }

    /// 检查字符串是否只包含字母和数字
    pub fn is_alphanumeric(s: &str) -> bool {
        !s.is_empty() && s.chars().all(|ch| ch.is_alphanumeric())
    }

    /// 驼峰命名转换（将下划线命名转换为驼峰命名）
    pub fn to_camel_case(s: &str) -> String {
        let words: Vec<&str> = s.split('_').collect();
        if words.is_empty() {
            return String::new();
        }

        let mut result = words[0].to_lowercase();
        for word in &words[1..] {
            if !word.is_empty() {
                let mut chars: Vec<char> = word.chars().collect();
                if !chars.is_empty() {
                    chars[0] = chars[0].to_uppercase().next().unwrap_or(chars[0]);
                    result.push_str(&chars.into_iter().collect::<String>());
                }
            }
        }
        result
    }

    /// 将字符串转换为烤串命名法
    pub fn to_kebab_case(s: &str) -> String {
        s.split_whitespace()
            .map(|word| word.to_lowercase())
            .collect::<Vec<_>>()
            .join("-")
    }

    /// 左填充字符串
    pub fn pad_left(s: &str, length: usize, pad_char: char) -> String {
        if s.len() >= length {
            return s.to_string();
        }

        let needed = length - s.len();
        let padding = pad_char.to_string().repeat(needed);
        format!("{}{}", padding, s)
    }

    /// 右填充字符串
    pub fn pad_right(s: &str, length: usize, pad_char: char) -> String {
        if s.len() >= length {
            return s.to_string();
        }

        let needed = length - s.len();
        let padding = pad_char.to_string().repeat(needed);
        format!("{}{}", s, padding)
    }

    /// 计算字符串的Unicode字符数
    pub fn unicode_length(s: &str) -> usize {
        s.chars().count()
    }

    /// 截取字符串（基于字符而非字节）
    pub fn substring(s: &str, start: usize, end: usize) -> String {
        let chars: Vec<char> = s.chars().collect();
        if start >= chars.len() || end > chars.len() || start > end {
            return String::new();
        }

        chars[start..end].iter().collect()
    }

    /// 反转字符串
    pub fn reverse(s: &str) -> String {
        s.chars().rev().collect()
    }

    /// 将字符串转换为标题格式（每个单词首字母大写）
    pub fn to_title_case(s: &str) -> String {
        s.split_whitespace()
            .map(|word| {
                let mut chars: Vec<char> = word.chars().collect();
                if !chars.is_empty() {
                    chars[0] = chars[0].to_uppercase().next().unwrap_or(chars[0]);
                    for i in 1..chars.len() {
                        chars[i] = chars[i].to_lowercase().next().unwrap_or(chars[i]);
                    }
                }
                chars.into_iter().collect()
            })
            .collect::<Vec<String>>()
            .join(" ")
    }

    /// 蛇形命名转换（将驼峰命名转换为下划线命名）
    pub fn to_snake_case(s: &str) -> String {
        let mut result = String::new();
        let mut prev_was_upper = false;

        for (i, ch) in s.chars().enumerate() {
            if ch.is_uppercase() {
                if i != 0 && !prev_was_upper {
                    result.push('_');
                }
                result.push(ch.to_lowercase().next().unwrap_or(ch));
                prev_was_upper = true;
            } else {
                result.push(ch);
                prev_was_upper = false;
            }
        }
        result
    }

    /// 计算字符串的相似度（使用简单的编辑距离算法）
    pub fn similarity(s1: &str, s2: &str) -> f64 {
        if s1.is_empty() && s2.is_empty() {
            return 1.0;
        }
        if s1.is_empty() || s2.is_empty() {
            return 0.0;
        }

        let len1 = s1.chars().count();
        let len2 = s2.chars().count();
        let max_len = len1.max(len2);

        // 简化的编辑距离计算
        let distance = Self::edit_distance(s1, s2);
        1.0 - (distance as f64 / max_len as f64)
    }

    /// 计算编辑距离
    fn edit_distance(s1: &str, s2: &str) -> usize {
        let chars1: Vec<char> = s1.chars().collect();
        let chars2: Vec<char> = s2.chars().collect();
        let len1 = chars1.len();
        let len2 = chars2.len();

        let mut matrix = vec![vec![0; len2 + 1]; len1 + 1];

        // 初始化第一行和第一列
        for i in 0..=len1 {
            matrix[i][0] = i;
        }
        for j in 0..=len2 {
            matrix[0][j] = j;
        }

        // 填充矩阵
        for i in 1..=len1 {
            for j in 1..=len2 {
                let cost = if chars1[i - 1] == chars2[j - 1] { 0 } else { 1 };
                matrix[i][j] = std::cmp::min(
                    std::cmp::min(
                        matrix[i - 1][j] + 1, // 删除
                        matrix[i][j - 1] + 1, // 插入
                    ),
                    matrix[i - 1][j - 1] + cost, // 替换
                );
            }
        }

        matrix[len1][len2]
    }

    /// 检查字符串是否是回文
    /// 检查一个字符串是否是回文。
    ///
    /// 此函数会过滤掉所有非字母和数字的字符。
    ///
    /// # 参数
    ///
    /// * `s` - 要检查的字符串切片。
    /// * `case_sensitive` - 一个布尔值，指示比较是否应区分大小写。
    ///   如果为 `false`，比较将在转换为小写后进行（默认行为）。
    ///
    /// # 返回值
    ///
    /// 如果字符串是回文，则为 `true`，否则为 `false`。
    ///
    /// # 示例
    ///
    /// ```
    /// // 默认行为：大小写不敏感
    /// assert_eq!(is_palindrome("A man, a plan, a canal: Panama", false), true);
    /// assert_eq!(is_palindrome("racecar", false), true);
    /// assert_eq!(is_palindrome("RaceCar", false), true);
    ///
    /// // 大小写敏感
    /// assert_eq!(is_palindrome("RaceCar", true), false);
    /// assert_eq!(is_palindrome("racecar", true), true);
    /// assert_eq!(is_palindrome("Aba", true), false);
    /// ```
    pub fn is_palindrome(s: &str, case_sensitive: bool) -> bool {
        // 创建一个处理过的字符迭代器
        // 根据 case_sensitive 参数决定是否转换为小写
        let processed_chars = s.chars().filter(|c| c.is_alphanumeric()).map(|c| {
            if case_sensitive {
                c
            } else {
                c.to_ascii_lowercase()
            }
        });
        // 创建一个反向的迭代器
        let mut forwards = processed_chars.clone();
        let mut backwards = processed_chars.rev();
        // 逐个比较，遇到不匹配立即返回 false
        loop {
            match (forwards.next(), backwards.next()) {
                (None, None) => return true, // 两边都到头了，是回文
                (Some(f), Some(b)) => {
                    if f != b {
                        return false; // 发现不匹配
                    }
                }
                // 理论上不会进入这个分支，因为长度相同
                _ => return false,
            }
        }
    }

    // 更简洁的写法，利用 itertools crate 的 `zip` 和 `all`
    // pub fn is_palindrome_best_itertools(s: &str, case_sensitive: bool) -> bool {
    //     use itertools::Itertools;
    //     let chars = s.chars().filter(|c| c.is_alphanumeric()).map(|c| {
    //         if case_sensitive {
    //             c
    //         } else {
    //             c.to_ascii_lowercase()
    //         }
    //     });

    //     chars.clone().zip(chars.rev()).all(|(a, b)| a == b)
    // }

    /// 随机打乱字符串中的字符
    pub fn shuffle(s: &str) -> String {
        use std::collections::hash_map::DefaultHasher;
        use std::hash::{Hash, Hasher};

        let mut chars: Vec<char> = s.chars().collect();
        let len = chars.len();

        // 使用简单的哈希函数作为伪随机数生成器
        let mut hasher = DefaultHasher::new();
        std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap()
            .as_nanos()
            .hash(&mut hasher);
        let mut seed = hasher.finish();

        for i in (1..len).rev() {
            // 简单的伪随机数生成
            seed = (seed * 1103515245 + 12345) & 0x7fffffff;
            let j = (seed as usize) % (i + 1);
            chars.swap(i, j);
        }

        chars.into_iter().collect()
    }
}
